package cn.tianyigps.tianyigpsapiv2.dao;

import cn.tianyigps.tianyigpsapiv2.exception.PermissionDeniedException;
import cn.tianyigps.tianyigpsapiv2.oauth2.context.ClientPrincipal;
import cn.tianyigps.tianyigpspublic.bean.BaseEntity;
import com.mongodb.client.result.UpdateResult;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.util.StringUtils;

import java.lang.reflect.ParameterizedType;
import java.util.Date;

/**
 * @Author: LiuHao
 * @Descirption:
 * @Date: 2019/4/12_11:18
 */
public abstract class BaseDao<T> {

    @Autowired
    private MongoTemplate mongoTemplate;

    private static final String ADMIN = "admin";

    private Class<T> clz;

    public Class<T> getClz() {
        if (clz == null) {
            clz = ((Class<T>) (((ParameterizedType) (this.getClass().getGenericSuperclass())).getActualTypeArguments()[0]));
        }
        return clz;
    }

    public boolean admin() {
        return ADMIN.equals(ClientPrincipal.getClientId());
    }

    public void insert(T entity) {
        ((BaseEntity) entity).setClientId(ClientPrincipal.getClientId());
        ((BaseEntity) entity).setCreateTime(new Date());
        mongoTemplate.insert(entity);
    }

    public void insert(T entity, String collection) {
        ((BaseEntity) entity).setClientId(ClientPrincipal.getClientId());
        ((BaseEntity) entity).setCreateTime(new Date());
        mongoTemplate.insert(entity, collection);
    }

    public void remove(T entity) {
        mongoTemplate.remove(entity);
    }

    public void remove(T entity, String collection) {
        mongoTemplate.remove(entity, collection);
    }

    //逻辑删除
    public boolean logicRemove(String id) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(new ObjectId(id)));
        query.addCriteria(Criteria.where("status").ne("0"));
        if (!admin()) {
            query.addCriteria(Criteria.where("clientId").is(ClientPrincipal.getClientId()));
        }
        Update update = new Update();
        update.set("status", "0");
        update.set("updateTime", new Date());
        return mongoTemplate.updateFirst(query, update, getClz()).isModifiedCountAvailable();
    }

    public boolean logicRemove(String id, String collection) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(new ObjectId(id)));
        query.addCriteria(Criteria.where("status").ne("0"));
        if (!admin()) {
            query.addCriteria(Criteria.where("clientId").is(ClientPrincipal.getClientId()));
        }
        Update update = new Update();
        update.set("status", "0");
        update.set("updateTime", new Date());
        return mongoTemplate.updateFirst(query, update, getClz(), collection).isModifiedCountAvailable();
    }

    public T findOne(String id) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(new ObjectId(id)));
        if (!admin()) {
            query.addCriteria(Criteria.where("clientId").is(ClientPrincipal.getClientId()));
        }
        query.addCriteria(Criteria.where("status").ne("0"));
        return mongoTemplate.findOne(query, getClz());
    }

    public T findOne(String id, String collection) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(new ObjectId(id)));
        if (!admin()) {
            query.addCriteria(Criteria.where("clientId").is(ClientPrincipal.getClientId()));
        }
        query.addCriteria(Criteria.where("status").ne("0"));
        return mongoTemplate.findOne(query, getClz(), collection);
    }

    public UpdateResult updateFirst(String id, Update update) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(new ObjectId(id)));
        query.addCriteria(Criteria.where("status").ne("0"));
        if (!admin()) {
            query.addCriteria(Criteria.where("clientId").is(ClientPrincipal.getClientId()));
        }
        update.set("updateTime", new Date());
        return mongoTemplate.updateFirst(query, update, getClz());
    }

    public UpdateResult updateFirst(String id, Update update, String collection) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(new ObjectId(id)));
        query.addCriteria(Criteria.where("status").ne("0"));
        if (!admin()) {
            query.addCriteria(Criteria.where("clientId").is(ClientPrincipal.getClientId()));
        }
        update.set("updateTime", new Date());
        return mongoTemplate.updateFirst(query, update, getClz(), collection);
    }

    public void save(T entity) throws PermissionDeniedException{
        if (!admin()) {
            String clientId = ClientPrincipal.getClientId();
            if(StringUtils.isEmpty(clientId) || !clientId.equals(((BaseEntity)entity).getClientId())){
                throw new PermissionDeniedException("clientId异常，没有权限!");
            }
        }
        mongoTemplate.save(entity);
    }

    public void save(T entity, String collection) throws PermissionDeniedException {
        if (!admin()) {
            String clientId = ClientPrincipal.getClientId();
            if(StringUtils.isEmpty(clientId) || !clientId.equals(((BaseEntity)entity).getClientId())){
                throw new PermissionDeniedException("clientId异常，没有权限!");
            }
        }
        mongoTemplate.save(entity, collection);
    }
}
